{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fdc3501d-d0a6-4a6f-a8af-cada198ed978",
   "metadata": {},
   "source": [
    "# Linear Pauli Rotations\n",
    "\n",
    "This function performs a rotation on a series of $m$ target qubits,\n",
    "where the rotation angle is a linear function of an $n$-qubit\n",
    "control register, as follows:\n",
    "\n",
    "$$\n",
    "\\left|x\\right\\rangle _{n}\\left|q\\right\\rangle\n",
    "_{m}\\rightarrow\\left|x\\right\\rangle\n",
    "_{n}\\prod_{k=1}^{m}\\left(\\cos\\left(\\frac{a_{k}}{2}x+\\frac{b_{k}}{2}\\right)-\n",
    "i\\sin\\left(\\frac{a_{k}}{2}x+\\frac{b_{k}}{2}\\right)P_{k}\\right)\\left|q_{k}\\right\\rangle\n",
    "$$\n",
    "\n",
    "where $\\left|x\\right\\rangle$ is the control register,\n",
    "$\\left|q\\right\\rangle$ is the target register, each $P_{k}$ is one of\n",
    "the three Pauli matrices $X$, $Y$, or $Z$, and $a_{k}$, $b_{k}$ are\n",
    "the user given slopes and offsets, respectively.\n",
    "\n",
    "For example, the operation of a linear $Y$ rotation on a zero-input\n",
    "qubit is\n",
    "\n",
    "$$\n",
    "\\left|x\\right\\rangle _{n}\\left|0\\right\\rangle\n",
    "\\rightarrow\\left|x\\right\\rangle _{n}\\left(\n",
    "\\cos\\left(\\frac{a}{2}x+\\frac{b}{2}\\right)\\left|0\\right\\rangle\n",
    "+\\sin\\left(\\frac{a}{2}x+\\frac{b}{2}\\right)\\left|1\\right\\rangle \\right)\n",
    "$$\n",
    "\n",
    "Such a rotation can be realized as a series of controlled rotations\n",
    "as follows:\n",
    "\n",
    "$$\n",
    "\\left[R_{y}\\left(2^{n-1}a\\right)\\right]^{x_{n-1}}\\cdots\n",
    "\\left[R_{y}\\left(2^{1}a\\right)\\right]^{x_{1}}\n",
    "\\left[R_{y}\\left(2^{0}a\\right)\\right]^{x_{0}}R_{y}\\left(b\\right)\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "819091bc-5d90-476d-b855-ce0b5213a8c7",
   "metadata": {},
   "source": [
    "Function: `linear_pauli_rotations`\n",
    "\n",
    "Arguments:\n",
    "\n",
    "- `bases: CArray[int]` - List of Pauli Enums.\n",
    "- `slopes: CArray[float]` - Rotation slopes for each of the given Pauli bases.\n",
    "- `offsets: CArray[float]` - Rotation offsets for each of the given Pauli bases.\n",
    "- `x: QArray[QBit]` - Quantum state to apply the rotation based on its value.\n",
    "- `q: QArray[QBit]` - List of indicator qubits for each of the given Pauli bases.\n",
    "\n",
    "Notice that `bases`, `slopes`, `offset` and `q` should be of the same size."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20f84a5c-2973-4610-a87c-6c30c77c00bc",
   "metadata": {},
   "source": [
    "## Example: Three Y Rotations Controlled by a 6-qubit State\n",
    "\n",
    "This example generates a quantum program with a $6$-qubit control\n",
    "state and $3$ target qubits, acted upon by Y rotations with different slopes and offsets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4a73e45a-d2b7-491a-b334-73f56e23ef8f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:47.770295Z",
     "iopub.status.busy": "2024-05-07T13:25:47.770087Z",
     "iopub.status.idle": "2024-05-07T13:25:50.393768Z",
     "shell.execute_reply": "2024-05-07T13:25:50.392918Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import (\n",
    "    Output,\n",
    "    Pauli,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    allocate,\n",
    "    create_model,\n",
    "    linear_pauli_rotations,\n",
    "    qfunc,\n",
    ")\n",
    "\n",
    "NUM_STATE_QUBITS = 6\n",
    "BASES = [Pauli.Y.value] * 3\n",
    "OFFSETS = [0.1, 0.3, 0.33]\n",
    "SLOPES = [2.1, 1, 7.0]\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(x: Output[QArray[QBit]], ind: Output[QArray[QBit]]):\n",
    "    allocate(NUM_STATE_QUBITS, x)\n",
    "    allocate(len(BASES), ind)\n",
    "    linear_pauli_rotations(BASES, SLOPES, OFFSETS, x, ind)\n",
    "\n",
    "\n",
    "qmod = create_model(main)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8aae1cc5-2ff5-47d4-abde-340b0f355ff0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:50.399400Z",
     "iopub.status.busy": "2024-05-07T13:25:50.397753Z",
     "iopub.status.idle": "2024-05-07T13:25:53.080375Z",
     "shell.execute_reply": "2024-05-07T13:25:53.079556Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import synthesize, write_qmod\n",
    "\n",
    "write_qmod(qmod, \"linear_pauli_rotations\")\n",
    "qprog = synthesize(qmod)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
